<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"wan-lei8.gitee.io","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
  </script>

  <meta name="description" content="如果有一天，你的Java程序长时间停顿，也许是它病了，需要用jstack拍个片子分析分析，才能诊断具体什么病症，是死锁综合征，还是死循环等其他病症，本文我们一起来学习jstack命令~  jstack 的功能 jstack用法 线程状态等基础回顾 实战案例1：jstack 分析死锁 实战案例2：jstack 分析CPU 过高  jstack 的功能jstack是JVM自带的Java堆栈跟踪工具，它">
<meta property="og:type" content="article">
<meta property="og:title" content="给你的Java程序拍个片子吧:jstack命令解析">
<meta property="og:url" content="https://wan-lei8.gitee.io/2022/01/24/%E7%BB%99%E4%BD%A0%E7%9A%84Java%E7%A8%8B%E5%BA%8F%E6%8B%8D%E4%B8%AA%E7%89%87%E5%AD%90%E5%90%A7-jstack%E5%91%BD%E4%BB%A4%E8%A7%A3%E6%9E%90/index.html">
<meta property="og:site_name" content="程序员西桐">
<meta property="og:description" content="如果有一天，你的Java程序长时间停顿，也许是它病了，需要用jstack拍个片子分析分析，才能诊断具体什么病症，是死锁综合征，还是死循环等其他病症，本文我们一起来学习jstack命令~  jstack 的功能 jstack用法 线程状态等基础回顾 实战案例1：jstack 分析死锁 实战案例2：jstack 分析CPU 过高  jstack 的功能jstack是JVM自带的Java堆栈跟踪工具，它">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPdO0OdCJ41EjGxjBkXL1gHndsAkwWibqv50APmueZWwJKaP67nz48tng/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPYicAQhWgxXRvuFzZz0gXib7JnibGDP9jrPyvqTDo6ftoSwsNC1YvZ75ZA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPFCFMejdKAPicgfkAx6Eaa2CvBOSFAwQt6HZaxUAeP88HCHANoF3Lfww/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPk8pUnYFqFdmCswT5zh8P5lkC6Fuxykw7gyaXSrI3n5ia8DJl5suXMcQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPtMYltl8xic4Micls7svoCiabdb01VFyVFj4geYNCRbnr207sup2M4x7XA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPnhjj4m4DV6CxCrlnt7butZcqf5XiaBnySDJQgp8WVF2DqTyDKnNJNcA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPaibqrGRzVD5icJztot8fZiaaPf26E10L45Sicicn8PQXmlSAsoDBUibvnVfA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPtSwLosvndDMcicsDFjVgUPZYZhSB63oVv3NbAQA2ImsjZWToq5zFJ5g/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPy2RBEn8gib48zib7X7s1460zktKXwMuJd61vcp9oYvePnqbmOw9nEZIA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPCFtAkz3cCs4Obexwlym6IjyOnVEVXTdUeWddpicOfBA4jxlbd64uiaqQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPLVLCFic60S0gDu1esRjE6bXUhj9qY7ibAiaBZQ75PekFApLASxPSERJ1w/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPEEl5CKOicgAdib0ZzicOmG7TLIEicUjNQwyhtggFNmGESpNBwLduZj205w/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPicCYKoGqicrzuJOs5HpyWWqVxg7PzQ8q71LQmA0RpVYrTPZE6HaJBQLw/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPEEl5CKOicgAdib0ZzicOmG7TLIEicUjNQwyhtggFNmGESpNBwLduZj205w/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="article:published_time" content="2022-01-24T07:59:09.000Z">
<meta property="article:modified_time" content="2022-01-24T08:04:19.083Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPdO0OdCJ41EjGxjBkXL1gHndsAkwWibqv50APmueZWwJKaP67nz48tng/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1">

<link rel="canonical" href="https://wan-lei8.gitee.io/2022/01/24/%E7%BB%99%E4%BD%A0%E7%9A%84Java%E7%A8%8B%E5%BA%8F%E6%8B%8D%E4%B8%AA%E7%89%87%E5%AD%90%E5%90%A7-jstack%E5%91%BD%E4%BB%A4%E8%A7%A3%E6%9E%90/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>给你的Java程序拍个片子吧:jstack命令解析 | 程序员西桐</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">程序员西桐</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">但行好事，莫问前程</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://wan-lei8.gitee.io/2022/01/24/%E7%BB%99%E4%BD%A0%E7%9A%84Java%E7%A8%8B%E5%BA%8F%E6%8B%8D%E4%B8%AA%E7%89%87%E5%AD%90%E5%90%A7-jstack%E5%91%BD%E4%BB%A4%E8%A7%A3%E6%9E%90/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="程序员西桐">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          给你的Java程序拍个片子吧:jstack命令解析
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2022-01-24 15:59:09 / 修改时间：16:04:19" itemprop="dateCreated datePublished" datetime="2022-01-24T15:59:09+08:00">2022-01-24</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <p>如果有一天，你的Java程序长时间停顿，也许是它病了，需要用jstack拍个片子分析分析，才能诊断具体什么病症，是死锁综合征，还是死循环等其他病症，本文我们一起来学习jstack命令~</p>
<ul>
<li>jstack 的功能</li>
<li>jstack用法</li>
<li>线程状态等基础回顾</li>
<li>实战案例1：jstack 分析死锁</li>
<li>实战案例2：jstack 分析CPU 过高</li>
</ul>
<h2 id="jstack-的功能"><a href="#jstack-的功能" class="headerlink" title="jstack 的功能"></a>jstack 的功能</h2><p>jstack是JVM自带的Java堆栈跟踪工具，它用于打印出给定的java进程ID、core file、远程调试服务的Java堆栈信息.</p>
<figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">jstack </span>prints <span class="keyword">Java </span>stack traces of <span class="keyword">Java </span>threads for a given <span class="keyword">Java </span>process <span class="keyword">orcore </span>file <span class="keyword">or </span>a remote <span class="built_in">debug</span> server. </span><br></pre></td></tr></table></figure>

<blockquote>
<ul>
<li>jstack命令用于生成虚拟机当前时刻的线程快照。</li>
<li>线程快照是当前虚拟机内每一条线程正在执行的方法堆栈的集合，生成线程快照的主要目的是定位线程出现长时间停顿的原因， 如线程间死锁、死循环、请求外部资源导致的长时间等待等问题。</li>
<li>线程出现停顿的时候通过jstack来查看各个线程的调用堆栈，就可以知道没有响应的线程到底在后台做什么事情，或者等待什么资源。</li>
<li>如果java程序崩溃生成core文件，jstack工具可以用来获得core文件的java stack和native stack的信息，从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。</li>
<li>另外，jstack工具还可以附属到正在运行的java程序中，看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态，jstack是非常有用的。</li>
</ul>
</blockquote>
<h2 id="jstack用法"><a href="#jstack用法" class="headerlink" title="jstack用法"></a>jstack用法</h2><p><strong>jstack 命令格式如下</strong></p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jstack <span class="selector-attr">[ option ]</span> pidjstack <span class="selector-attr">[ option ]</span> executable corejstack <span class="selector-attr">[ option ]</span> <span class="selector-attr">[server-id@]</span>remote-hostname-or-IP</span><br></pre></td></tr></table></figure>

<ul>
<li>executable Java executable from which the core dump was produced.(可能是产生core dump的java可执行程序)</li>
<li>core 将被打印信息的core dump文件</li>
<li>remote-hostname-or-IP 远程debug服务的主机名或ip</li>
<li>server-id 唯一id,假如一台主机上多个远程debug服务</li>
</ul>
<p><strong>最常用的是</strong></p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jstack [option] &lt;pid&gt;  <span class="regexp">//</span> 打印某个进程的堆栈信息</span><br></pre></td></tr></table></figure>

<p><strong>option参数说明如下：</strong></p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPdO0OdCJ41EjGxjBkXL1gHndsAkwWibqv50APmueZWwJKaP67nz48tng/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<table>
<thead>
<tr>
<th align="left">选项</th>
<th align="left">作用</th>
</tr>
</thead>
<tbody><tr>
<td align="left">-F</td>
<td align="left">当正常输出的请求不被响应时，强制输出线程堆栈</td>
</tr>
<tr>
<td align="left">-m</td>
<td align="left">如果调用到本地方法的话，可以显示C/C++的堆栈</td>
</tr>
<tr>
<td align="left">-l</td>
<td align="left">除堆栈外，显示关于锁的附加信息，在发生死锁时可以用jstack -l pid来观察锁持有情况</td>
</tr>
</tbody></table>
<h2 id="线程状态等基础回顾"><a href="#线程状态等基础回顾" class="headerlink" title="线程状态等基础回顾"></a>线程状态等基础回顾</h2><h3 id="线程状态简介"><a href="#线程状态简介" class="headerlink" title="线程状态简介"></a>线程状态简介</h3><p>jstack用于生成线程快照的，我们分析线程的情况，需要复习一下线程状态吧，拿小凳子坐好，复习一下啦~<img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPYicAQhWgxXRvuFzZz0gXib7JnibGDP9jrPyvqTDo6ftoSwsNC1YvZ75ZA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p><strong>Java语言定义了6种线程池状态：</strong></p>
<ul>
<li>New：创建后尚未启动的线程处于这种状态，不会出现在Dump中。</li>
<li>RUNNABLE：包括Running和Ready。线程开启start（）方法，会进入该状态，在虚拟机内执行的。</li>
<li>Waiting：无限的等待另一个线程的特定操作。</li>
<li>Timed Waiting：有时限的等待另一个线程的特定操作。</li>
<li>阻塞（Blocked）：在程序等待进入同步区域的时候，线程将进入这种状态，在等待监视器锁。</li>
<li>结束（Terminated）：已终止线程的线程状态，线程已经结束执行。</li>
</ul>
<p><strong>Dump文件的线程状态一般其实就以下3种：</strong></p>
<ul>
<li>RUNNABLE，线程处于执行中</li>
<li>BLOCKED，线程被阻塞</li>
<li>WAITING，线程正在等待</li>
</ul>
<h3 id="Monitor-监视锁"><a href="#Monitor-监视锁" class="headerlink" title="Monitor 监视锁"></a>Monitor 监视锁</h3><p>因为Java程序一般都是多线程运行的，Java多线程跟监视锁环环相扣，所以我们分析线程状态时，也需要回顾一下Monitor监视锁知识。</p>
<p>有关于线程同步关键字Synchronized与监视锁的爱恨情仇，有兴趣的伙伴可以看一下我这篇文章<a target="_blank" rel="noopener" href="http://mp.weixin.qq.com/s?__biz=MzIwOTE2MzU4NA==&mid=2247483711&idx=1&sn=884f5c0f3e286226e35341509a0db546&chksm=97794510a00ecc06a5e3a77ea60b9476e51d1b6025cc1e86e0a9ab22ff36aa76666e3e400039&scene=21#wechat_redirect">Synchronized解析——如果你愿意一层一层剥开我的心</a></p>
<p>Monitor的工作原理图如下：</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPFCFMejdKAPicgfkAx6Eaa2CvBOSFAwQt6HZaxUAeP88HCHANoF3Lfww/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<ul>
<li>线程想要获取monitor,首先会进入Entry Set队列，它是Waiting Thread，线程状态是Waiting for monitor entry。</li>
<li>当某个线程成功获取对象的monitor后,进入Owner区域，它就是Active Thread。</li>
<li>如果线程调用了wait()方法，则会进入Wait Set队列，它会释放monitor锁，它也是Waiting Thread，线程状态in Object.wait()</li>
<li>如果其他线程调用 notify() / notifyAll() ，会唤醒Wait Set中的某个线程，该线程再次尝试获取monitor锁，成功即进入Owner区域。</li>
</ul>
<h3 id="Dump-文件分析关注重点"><a href="#Dump-文件分析关注重点" class="headerlink" title="Dump 文件分析关注重点"></a>Dump 文件分析关注重点</h3><ul>
<li>runnable，线程处于执行中</li>
<li>deadlock，死锁（重点关注）</li>
<li>blocked，线程被阻塞 （重点关注）</li>
<li>Parked，停止</li>
<li>locked，对象加锁</li>
<li>waiting，线程正在等待</li>
<li>waiting to lock 等待上锁</li>
<li>Object.wait()，对象等待中</li>
<li>waiting for monitor entry 等待获取监视器（重点关注）</li>
<li>Waiting on condition，等待资源（重点关注），最常见的情况是线程在等待网络的读写</li>
</ul>
<h2 id="实战案例1：jstack-分析死锁问题"><a href="#实战案例1：jstack-分析死锁问题" class="headerlink" title="实战案例1：jstack 分析死锁问题"></a>实战案例1：jstack 分析死锁问题</h2><ul>
<li>什么是死锁？</li>
<li>如何用jstack排查死锁？</li>
</ul>
<h3 id="什么是死锁？"><a href="#什么是死锁？" class="headerlink" title="什么是死锁？"></a>什么是死锁？</h3><p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPk8pUnYFqFdmCswT5zh8P5lkC6Fuxykw7gyaXSrI3n5ia8DJl5suXMcQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>死锁是指两个或两个以上的线程在执行过程中，因争夺资源而造成的一种互相等待的现象，若无外力作用，它们都将无法进行下去。</p>
<h3 id="如何用如何用jstack排查死锁问题"><a href="#如何用如何用jstack排查死锁问题" class="headerlink" title="如何用如何用jstack排查死锁问题"></a>如何用如何用jstack排查死锁问题</h3><p>先来看一段会产生死锁的Java程序，源码如下：</p>
<figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/** * Java 死锁demo */</span>public <span class="keyword">class</span> DeathLockTest &#123;    <span class="keyword">private</span> static Lock lock1 = <span class="keyword">new</span> <span class="constructor">ReentrantLock()</span>;    <span class="keyword">private</span> static Lock lock2 = <span class="keyword">new</span> <span class="constructor">ReentrantLock()</span>;</span><br><span class="line">    public static void death<span class="constructor">Lock()</span> &#123;        Thread t1 = <span class="keyword">new</span> <span class="constructor">Thread()</span> &#123;            @Override            public void run<span class="literal">()</span> &#123;                <span class="keyword">try</span> &#123;                    lock1.lock<span class="literal">()</span>;                    <span class="module-access"><span class="module"><span class="identifier">System</span>.</span></span>out.println(<span class="module-access"><span class="module"><span class="identifier">Thread</span>.</span></span>current<span class="constructor">Thread()</span>.get<span class="constructor">Name()</span> + <span class="string">&quot; get the lock1&quot;</span>);                    <span class="module-access"><span class="module"><span class="identifier">Thread</span>.</span></span>sleep(<span class="number">1000</span>);                    lock2.lock<span class="literal">()</span>;                    <span class="module-access"><span class="module"><span class="identifier">System</span>.</span></span>out.println(<span class="module-access"><span class="module"><span class="identifier">Thread</span>.</span></span>current<span class="constructor">Thread()</span>.get<span class="constructor">Name()</span> + <span class="string">&quot; get the lock2&quot;</span>);                &#125; catch (InterruptedException e) &#123;                    e.print<span class="constructor">StackTrace()</span>;                &#125;            &#125;        &#125;;        Thread t2 = <span class="keyword">new</span> <span class="constructor">Thread()</span> &#123;            @Override            public void run<span class="literal">()</span> &#123;                <span class="keyword">try</span> &#123;                    lock2.lock<span class="literal">()</span>;                    <span class="module-access"><span class="module"><span class="identifier">System</span>.</span></span>out.println(<span class="module-access"><span class="module"><span class="identifier">Thread</span>.</span></span>current<span class="constructor">Thread()</span>.get<span class="constructor">Name()</span> + <span class="string">&quot; get the lock2&quot;</span>);                    <span class="module-access"><span class="module"><span class="identifier">Thread</span>.</span></span>sleep(<span class="number">1000</span>);                    lock1.lock<span class="literal">()</span>;                    <span class="module-access"><span class="module"><span class="identifier">System</span>.</span></span>out.println(<span class="module-access"><span class="module"><span class="identifier">Thread</span>.</span></span>current<span class="constructor">Thread()</span>.get<span class="constructor">Name()</span> + <span class="string">&quot; get the lock1&quot;</span>);                &#125; catch (InterruptedException e) &#123;                    e.print<span class="constructor">StackTrace()</span>;                &#125;            &#125;        &#125;;        <span class="comment">//设置线程名字，方便分析堆栈信息        t1.setName(&quot;mythread-jay&quot;);        t2.setName(&quot;mythread-tianluo&quot;);        t1.start();        t2.start();    &#125;    public static void main(String[] args) &#123;        deathLock();    &#125;&#125;</span></span><br></pre></td></tr></table></figure>

<p>运行结果：<img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPtMYltl8xic4Micls7svoCiabdb01VFyVFj4geYNCRbnr207sup2M4x7XA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">显然，线程jay和线程tianluo都是只执行到一半，就陷入了阻塞等待状态~</p>
<h3 id="jstack排查Java死锁步骤"><a href="#jstack排查Java死锁步骤" class="headerlink" title="jstack排查Java死锁步骤"></a>jstack排查Java死锁步骤</h3><ul>
<li>在终端中输入jsp查看当前运行的java程序</li>
<li>使用 jstack -l pid 查看线程堆栈信息</li>
<li>分析堆栈信息</li>
</ul>
<h3 id="在终端中输入jsp查看当前运行的java程序"><a href="#在终端中输入jsp查看当前运行的java程序" class="headerlink" title="在终端中输入jsp查看当前运行的java程序"></a>在终端中输入jsp查看当前运行的java程序</h3><p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPnhjj4m4DV6CxCrlnt7butZcqf5XiaBnySDJQgp8WVF2DqTyDKnNJNcA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">通过使用 jps 命令获取需要监控的进程的pid，我们找到了 <code>23780DeathLockTest</code></p>
<h3 id="使用-jstack-l-pid-查看线程堆栈信息"><a href="#使用-jstack-l-pid-查看线程堆栈信息" class="headerlink" title="使用 jstack -l pid 查看线程堆栈信息"></a>使用 jstack -l pid 查看线程堆栈信息</h3><p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPaibqrGRzVD5icJztot8fZiaaPf26E10L45Sicicn8PQXmlSAsoDBUibvnVfA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">由上图，可以清晰看到<strong>死锁</strong>信息：</p>
<ul>
<li>mythread-tianluo 等待这个锁 “0x00000000d61ae3a0”，这个锁是由mythread-jay线程持有。</li>
<li>mythread-jay线程等待这个锁“0x00000000d61ae3d0”,这个锁是由mythread-tianluo 线程持有。</li>
</ul>
<h3 id="还原死锁真相"><a href="#还原死锁真相" class="headerlink" title="还原死锁真相"></a>还原死锁真相</h3><p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPtSwLosvndDMcicsDFjVgUPZYZhSB63oVv3NbAQA2ImsjZWToq5zFJ5g/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"><strong>“mythread-tianluo”线程堆栈信息分析如下：</strong></p>
<ul>
<li>mythread-tianluo的线程处于等待（waiting）状态，持有“0x00000000d61ae3d0”锁，等待“0x00000000d61ae3a0”的锁</li>
</ul>
<p><strong>“mythread-jay”线程堆栈信息分析如下：</strong></p>
<ul>
<li>mythread-tianluo的线程处于等待（waiting）状态，持有“0x00000000d61ae3a0”锁，等待“0x00000000d61ae3d0”的锁</li>
</ul>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPy2RBEn8gib48zib7X7s1460zktKXwMuJd61vcp9oYvePnqbmOw9nEZIA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<h2 id="实战案例2：jstack-分析CPU过高问题"><a href="#实战案例2：jstack-分析CPU过高问题" class="headerlink" title="实战案例2：jstack 分析CPU过高问题"></a>实战案例2：jstack 分析CPU过高问题</h2><p>来个导致CPU过高的demo程序，一个死循环，哈哈~</p>
<figure class="highlight arduino"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/** * 有个导致CPU过高程序的demo，死循环 */</span><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JstackCase</span> &#123;</span></span><br><span class="line">     <span class="keyword">private</span> <span class="keyword">static</span> ExecutorService executorService = Executors.<span class="built_in">newFixedThreadPool</span>(<span class="number">5</span>);</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(<span class="keyword">String</span>[] args)</span> </span>&#123;</span><br><span class="line">        <span class="built_in">Task</span> task1 = <span class="keyword">new</span> <span class="built_in"><span class="built_in">Task</span></span>();        <span class="built_in">Task</span> task2 = <span class="keyword">new</span> <span class="built_in"><span class="built_in">Task</span></span>();        executorService.<span class="built_in">execute</span>(task1);        executorService.<span class="built_in">execute</span>(task2);    &#125;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> Object lock = <span class="keyword">new</span> <span class="built_in">Object</span>();</span><br><span class="line">    <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Task</span> <span class="title">implements</span> <span class="title">Runnable</span>&#123;</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;            <span class="built_in">synchronized</span> (lock)&#123;                <span class="keyword">long</span> sum = <span class="number">0L</span>;                <span class="keyword">while</span> (<span class="literal">true</span>)&#123;                    sum += <span class="number">1</span>;                &#125;            &#125;        &#125;    &#125;&#125;</span><br></pre></td></tr></table></figure>

<h3 id="jstack-分析CPU过高步骤"><a href="#jstack-分析CPU过高步骤" class="headerlink" title="jstack 分析CPU过高步骤"></a>jstack 分析CPU过高步骤</h3><ul>
<li>top</li>
<li>top -Hp pid</li>
<li>jstack pid</li>
<li> jstack -l [PID] &gt;/tmp/log.txt</li>
<li>分析堆栈信息</li>
</ul>
<h3 id="1-top"><a href="#1-top" class="headerlink" title="1.top"></a>1.top</h3><p>在服务器上，我们可以通过top命令查看各个进程的cpu使用情况，它默认是按cpu使用率由高到低排序的<img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPCFtAkz3cCs4Obexwlym6IjyOnVEVXTdUeWddpicOfBA4jxlbd64uiaqQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>由上图中，我们可以找出pid为21340的java进程，它占用了最高的cpu资源，凶手就是它，哈哈！</p>
<h3 id="2-top-Hp-pid"><a href="#2-top-Hp-pid" class="headerlink" title="2. top -Hp pid"></a>2. top -Hp pid</h3><p>通过top -Hp 21340可以查看该进程下，各个线程的cpu使用情况，如下：<img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPLVLCFic60S0gDu1esRjE6bXUhj9qY7ibAiaBZQ75PekFApLASxPSERJ1w/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>可以发现pid为21350的线程，CPU资源占用最高<del>，嘻嘻，小本本把它记下来，接下来拿jstack给它拍片子</del></p>
<h3 id="3-jstack-pid"><a href="#3-jstack-pid" class="headerlink" title="3. jstack pid"></a>3. jstack pid</h3><p>通过top命令定位到cpu占用率较高的线程之后，接着使用jstack pid命令来查看当前java进程的堆栈状态， <code>jstack21350</code>后，内容如下：<img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPEEl5CKOicgAdib0ZzicOmG7TLIEicUjNQwyhtggFNmGESpNBwLduZj205w/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<h3 id="4-jstack-l-PID-gt-tmp-log-txt"><a href="#4-jstack-l-PID-gt-tmp-log-txt" class="headerlink" title="4. jstack -l [PID] &gt;/tmp/log.txt"></a>4. jstack -l [PID] &gt;/tmp/log.txt</h3><p>其实，前3个步骤，堆栈信息已经出来啦。但是一般在生成环境，我们可以把这些堆栈信息打到一个文件里，再回头仔细分析哦~</p>
<h3 id="5-分析堆栈信息"><a href="#5-分析堆栈信息" class="headerlink" title="5. 分析堆栈信息"></a>5. 分析堆栈信息</h3><p>我们把占用cpu资源较高的线程pid（本例子是21350），将该pid转成16进制的值</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPicCYKoGqicrzuJOs5HpyWWqVxg7PzQ8q71LQmA0RpVYrTPZE6HaJBQLw/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">在thread dump中，每个线程都有一个nid，我们找到对应的nid（5366），发现一直在跑（24行）</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPEEl5CKOicgAdib0ZzicOmG7TLIEicUjNQwyhtggFNmGESpNBwLduZj205w/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>这个时候，可以去检查代码是否有问题啦~ 当然，也建议隔段时间再执行一次stack命令，再一份获取thread dump，毕竟两次拍片结果（jstack）对比，更准确嘛~</p>

    </div>
<div>
  
    <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
    
</div>

  
</div>

    
    
    
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://wan-lei8.gitee.io/2022/01/24/%E7%BB%99%E4%BD%A0%E7%9A%84Java%E7%A8%8B%E5%BA%8F%E6%8B%8D%E4%B8%AA%E7%89%87%E5%AD%90%E5%90%A7-jstack%E5%91%BD%E4%BB%A4%E8%A7%A3%E6%9E%90/" title="给你的Java程序拍个片子吧:jstack命令解析">https://wan-lei8.gitee.io/2022/01/24/给你的Java程序拍个片子吧-jstack命令解析/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" rel="noopener" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2022/01/17/idea%E8%AE%BE%E7%BD%AE%E4%B8%BB%E9%A2%98/" rel="prev" title="idea设置主题">
      <i class="fa fa-chevron-left"></i> idea设置主题
    </a></div>
      <div class="post-nav-item">
    <a href="/2022/01/24/%E7%B4%A2%E5%BC%95%E4%BC%98%E5%8C%96/" rel="next" title="索引优化">
      索引优化 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#jstack-%E7%9A%84%E5%8A%9F%E8%83%BD"><span class="nav-number">1.</span> <span class="nav-text">jstack 的功能</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#jstack%E7%94%A8%E6%B3%95"><span class="nav-number">2.</span> <span class="nav-text">jstack用法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BA%BF%E7%A8%8B%E7%8A%B6%E6%80%81%E7%AD%89%E5%9F%BA%E7%A1%80%E5%9B%9E%E9%A1%BE"><span class="nav-number">3.</span> <span class="nav-text">线程状态等基础回顾</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%BA%BF%E7%A8%8B%E7%8A%B6%E6%80%81%E7%AE%80%E4%BB%8B"><span class="nav-number">3.1.</span> <span class="nav-text">线程状态简介</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Monitor-%E7%9B%91%E8%A7%86%E9%94%81"><span class="nav-number">3.2.</span> <span class="nav-text">Monitor 监视锁</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Dump-%E6%96%87%E4%BB%B6%E5%88%86%E6%9E%90%E5%85%B3%E6%B3%A8%E9%87%8D%E7%82%B9"><span class="nav-number">3.3.</span> <span class="nav-text">Dump 文件分析关注重点</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%AE%9E%E6%88%98%E6%A1%88%E4%BE%8B1%EF%BC%9Ajstack-%E5%88%86%E6%9E%90%E6%AD%BB%E9%94%81%E9%97%AE%E9%A2%98"><span class="nav-number">4.</span> <span class="nav-text">实战案例1：jstack 分析死锁问题</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF%E6%AD%BB%E9%94%81%EF%BC%9F"><span class="nav-number">4.1.</span> <span class="nav-text">什么是死锁？</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%A6%82%E4%BD%95%E7%94%A8%E5%A6%82%E4%BD%95%E7%94%A8jstack%E6%8E%92%E6%9F%A5%E6%AD%BB%E9%94%81%E9%97%AE%E9%A2%98"><span class="nav-number">4.2.</span> <span class="nav-text">如何用如何用jstack排查死锁问题</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#jstack%E6%8E%92%E6%9F%A5Java%E6%AD%BB%E9%94%81%E6%AD%A5%E9%AA%A4"><span class="nav-number">4.3.</span> <span class="nav-text">jstack排查Java死锁步骤</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9C%A8%E7%BB%88%E7%AB%AF%E4%B8%AD%E8%BE%93%E5%85%A5jsp%E6%9F%A5%E7%9C%8B%E5%BD%93%E5%89%8D%E8%BF%90%E8%A1%8C%E7%9A%84java%E7%A8%8B%E5%BA%8F"><span class="nav-number">4.4.</span> <span class="nav-text">在终端中输入jsp查看当前运行的java程序</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8-jstack-l-pid-%E6%9F%A5%E7%9C%8B%E7%BA%BF%E7%A8%8B%E5%A0%86%E6%A0%88%E4%BF%A1%E6%81%AF"><span class="nav-number">4.5.</span> <span class="nav-text">使用 jstack -l pid 查看线程堆栈信息</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%BF%98%E5%8E%9F%E6%AD%BB%E9%94%81%E7%9C%9F%E7%9B%B8"><span class="nav-number">4.6.</span> <span class="nav-text">还原死锁真相</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%AE%9E%E6%88%98%E6%A1%88%E4%BE%8B2%EF%BC%9Ajstack-%E5%88%86%E6%9E%90CPU%E8%BF%87%E9%AB%98%E9%97%AE%E9%A2%98"><span class="nav-number">5.</span> <span class="nav-text">实战案例2：jstack 分析CPU过高问题</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#jstack-%E5%88%86%E6%9E%90CPU%E8%BF%87%E9%AB%98%E6%AD%A5%E9%AA%A4"><span class="nav-number">5.1.</span> <span class="nav-text">jstack 分析CPU过高步骤</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-top"><span class="nav-number">5.2.</span> <span class="nav-text">1.top</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-top-Hp-pid"><span class="nav-number">5.3.</span> <span class="nav-text">2. top -Hp pid</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-jstack-pid"><span class="nav-number">5.4.</span> <span class="nav-text">3. jstack pid</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-jstack-l-PID-gt-tmp-log-txt"><span class="nav-number">5.5.</span> <span class="nav-text">4. jstack -l [PID] &gt;&#x2F;tmp&#x2F;log.txt</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5-%E5%88%86%E6%9E%90%E5%A0%86%E6%A0%88%E4%BF%A1%E6%81%AF"><span class="nav-number">5.6.</span> <span class="nav-text">5. 分析堆栈信息</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt=""
      src="/images/avatar.png">
  <p class="site-author-name" itemprop="name"></p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives">
          <span class="site-state-item-count">41</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/yourname" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;yourname" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="/malegod958@163.com" title="E-Mail → malegod958@163.com"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>
  <div class="cc-license motion-element" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 2018 – 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">万磊</span>
</div>
  <div class="powered-by">

  </div>

        








      </div>
    </footer>
  </div>

  
  
  <script color='' opacity='0.5' zIndex='-1' count='99' src="/lib/canvas-nest/canvas-nest.min.js"></script>
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

  
	<script type="text/javascript" src="//cdn.bootcss.com/canvas-nest.js/1.0.0/canvas-nest.min.js"></script>
	

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body>
</html>
<!-- 页面点击小红心 -->
<script type="text/javascript" src="/js/src/clicklove.js"></script>
